package com.hadron.media.slideshow.patterns.mvc.model 
{
	import com.hadron.media.slideshow.data.SlideshowVars;
	import com.hadron.media.slideshow.enum.SlideshowStatus;
	import com.hadron.media.slideshow.events.SlideshowModelEvent;
	import com.hadron.media.slideshow.items.ISlideshowItem;
	import com.hadron.media.slideshow.parser.ISlideshowXMLParser;
	import com.hadron.media.slideshow.parser.SlideshowXmlParser;
	import com.hadron.media.slideshow.patterns.factory.ItemCreator;
	import com.hadron.transitions.events.TransitionEvent;
	import temple.core.CoreEventDispatcher;
	import temple.data.collections.Collection;
	import temple.data.collections.HashMap;
	import temple.data.collections.ICollection;
	import com.greensock.loading.LoaderMax;
	import com.greensock.loading.XMLLoader;
	import com.greensock.events.LoaderEvent;
	import com.greensock.loading.ImageLoader;
	import temple.utils.TimeOut;
	import temple.utils.types.ObjectUtils;
	
	/**
	 * SlideshowModel
	 * @author Hadron
	 * date created: 05-22-2011
	 */
	
	public class SlideshowModel extends CoreEventDispatcher implements ISlideshowModel
	{
		///////////////////////////
		// FIELDS
		///////////////////////////
		/** @private */
		private var _currentIndex:int = -1;
		/** @private */
		private var _currentItem:ISlideshowItem;
		/** @private */
		private var _items:ICollection;
		/** @private */
		private var _xmlURL:String;
		/** @private */
		private var _autoPlay:Boolean;
		/** @private */
		private var _autoLoad:Boolean;
		/** @private */
		private var _displayTime:Number;
		/** @private */
		private var _fadeTime:Number;
		/** @private */
		private var _background:Boolean = false;
		/** @private */
		private var _backgroundColor:uint = 0x000000;
		/** @private */
		private var _backgroundAlpha:Number = 1;
		/** @private */
		private var _debug:Boolean = false;
		/** @private */
		private var _status:SlideshowStatus = SlideshowStatus.NOT_INITIALIZED;
		/** @private */
		private var _itemsByName:HashMap;
		/** @private */
		private var _itemsByURL:HashMap;
		/** @private */
		private var _parser:ISlideshowXMLParser;
		/** @private */
		private var _vars:Object;
		/** @private */
		private var _transition:Boolean;
		/** @private */
		private var timeout:TimeOut;
		/**
		  * This method constructs instance of this class
		 */
		public function SlideshowModel() 
		{
			init();
		}
		
		/*------------------- PUBLIC METHODS ------------------*/
		public function flush():void
		{
			_items.clear();
			_currentIndex = 0;
		}
		
		public function load():void 
		{
			if (debug) 
				logDebug('assets loading');
			//start loading contents
			LoaderMax.activate([ImageLoader]);
			var loader:XMLLoader = new XMLLoader(xmlURL, { name:'xmlLoader' } );
			loader.addEventListener(LoaderEvent.COMPLETE, handleImagesComplete);
			loader.load(); 
		}
		
		public function clear():void
		{
			items.clear();
			itemsByName.destruct();
			itemsByURL.destruct();
			_currentItem = null;
			_currentIndex = -1;
			if (_parser) 
				_parser = null;
			
			if (timeout) 
				timeout.destruct();
			
		}
		
		public function resetDisplayTimer():void
		{
			if (debug) logDebug('resetDisplayTimer');
			if(timeout) timeout.destruct();
			timeout = new TimeOut(showNext, displayTime * 1000);
		}
		
		/*------------------ GETTERS & SETTERS -----------------*/
		public function get background():Boolean { return _background; }
		public function set background(value:Boolean):void { _background = value; }
		
		public function get backgroundColor():uint { return _backgroundColor; };
		public function set backgroundColor(value:uint):void { _backgroundColor = value; }
		
		public function get backgroundAlpha():Number { return _backgroundColor; }
		public function set backgroundAlpha(value:Number):void 
		{
			_backgroundAlpha = Math.min(Math.max(value, 0), 1);  
		}
		
		/* INTERFACE temple.debug.IDebuggable*/
		public function set debug(value:Boolean):void 
		{	_debug = value;
			if (_debug) logDebug('debug mode on'); 
		}
		public function get debug():Boolean { return _debug; }
		
		public function get items():ICollection { return _items; }
		
		public function get status():SlideshowStatus { return _status; }
		public function set status(value:SlideshowStatus):void { _status = value; }
		
		public function get autoPlay():Boolean { return _autoPlay; }
		public function set autoPlay(value:Boolean):void { _autoPlay = value; }
		
		public function get autoLoad():Boolean { return _autoLoad; }
		public function set autoLoad(value:Boolean):void { _autoLoad = value; }
		
		public function get displayTime():Number { return _displayTime;	}
		public function set displayTime(value:Number):void { _displayTime = value;	}
		
		public function get fadeTime():Number {	return _fadeTime; }
		public function set fadeTime(value:Number):void { _fadeTime = value; }
		
		public function get currentIndex():uint { return _currentIndex;	}
		public function set currentIndex(value:uint):void 
		{ 
			if (status == SlideshowStatus.LOADED)
			{
				_currentIndex = (value > _items.length - 1) ? 0 : value; 
				_currentItem = _items.getItemAt(_currentIndex) as ISlideshowItem;
				dispatchEvent(new SlideshowModelEvent(SlideshowModelEvent.ITEM_CHANGE));
			}
		}
		
		public function get currentItem():ISlideshowItem { return _currentItem; }
		public function set currentItem(value:ISlideshowItem):void 
		{ 
			_currentItem = value; 
			//_currentIndex = 
			dispatchEvent(new SlideshowModelEvent(SlideshowModelEvent.ITEM_CHANGE));
		}
		
		public function set xmlURL(value:String):void 
		{
			_xmlURL = value;
				if (_autoLoad)
					load();
		}
		
		public function get xmlURL():String { return _xmlURL; }
		public function get itemsByName():HashMap { return _itemsByName; }
		public function get itemsByURL():HashMap { return _itemsByURL; }
		public function get vars():Object { return _vars; }
		public function set vars(value:Object):void { _vars = value; }
		
		
		public function get transition():Boolean { return _transition; }
		public function set transition(value:Boolean):void { _transition = value; }
		
		/*------------------- PRIVATE METHODS ------------------*/
		private function init():void 
		{
			_items = new Collection([]);
		}
		
		private function showNext():void 
		{
			currentIndex++;
		}
		
		private function assignVars():void 
		{
			if (this.vars.isSlideshowVars) { 
				this.vars = vars.vars;
			}
			// read slideshowVars or set default parameters 
			autoPlay = (this.vars.autoPlay != undefined) ? Boolean(this.vars.autoPlay) : false;
			autoLoad = (this.vars.autoLoad != undefined) ? Boolean(this.vars.autoLoad) : true;
			displayTime = (this.vars.displayTime != undefined) ? Number(this.vars.displayTime) : 2;
			fadeTime = (this.vars.fadeTime != undefined) ? Number(this.vars.fadeTime) : .5;
			debug = (this.vars.debug != undefined) ? Boolean(this.vars.debug) : false;
			background = (this.vars.background != undefined) ? Boolean(this.vars.background) : true;
			backgroundColor = (this.vars.backgroundColor != undefined) ? uint(this.vars.backgroundColor) : 0x000000;
			backgroundAlpha = (this.vars.backgroundAlpha != undefined) ? Number(this.vars.backgroundAlpha) : 1;
		}
		
		/* ---------------  EVENT HANDLERS ------------------ */
		private function handleImagesComplete(e:LoaderEvent):void 
		{
			//init parser lazy
			if (!_parser) {
				_parser = new SlideshowXmlParser();
				//if parser parsed xml correctly - check if xml contained 
				// necessary settings data - if yes - set it to vars object
				
				if (_parser.parseXML(XMLLoader(e.target).getContent(xmlURL))) {
					if (_parser.vars) {
						vars = _parser.vars;
						assignVars();
					}
					_itemsByName = _parser.itemsByName;
					_itemsByURL = _parser.itemsByURL;
					_items = _parser.items;
				} else {
					throw new Error("parser couldn't parse XML file correctly");
				}
			} else {
				//TODO: flush parser content
			}
			if (debug) logDebug('all images loaded');
			status = SlideshowStatus.LOADED;
			dispatchEvent(new SlideshowModelEvent(SlideshowModelEvent.ITEMS_LOAD_COMPLETE));
		}
	}
}